/*
* INSANE - Interactive Structural Analysis Environment
*
* Copyright (C) 2003-2005
* Universidade Federal de Minas Gerais
* Escola de Engenharia
* Departamento de Engenharia de Estruturas
* 
* Author's email :    insane@dees.ufmg.br
* Author's website :  http://www.dees.ufmg.br/insane
* 
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or any later version.
* 
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU General Public License for more details.
* 
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
*/
package br.ufmg.dees.insane.analysisModel;

import java.io.Serializable;
import java.util.ArrayList;

import br.ufmg.dees.insane.util.IMatrix;
import br.ufmg.dees.insane.util.IVector;
import br.ufmg.dees.insane.util.pointValues.PointValues;
import br.ufmg.dees.insane.util.pointValues.StringPointValues;

/** A class representing analysis model referring to the
 *  quadrilateral plate-bending element of nine node 
 *  developed by Hughes and Cohen, called Heterosis.
 * @author Samir
 * @since 14/07/2006
 */
public class Heterosis extends ReissnerMindlinPlate implements Serializable {

	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;

	/**Constructs a Heterosis AnalysisModel.*/
	public Heterosis(){
	}
	
    /* (non-Javadoc)
     * @see br.ufmg.dees.insane.analysisModel.AnalysisModel#getType()
     */
    public String getLabel() {
        return "Heterosis";
    }

    /* (non-Javadoc)
     * @see br.ufmg.dees.insane.analysisModel.AnalysisModel#getInternalVariableOperator(br.ufmg.dees.insane.util.IMatrix, br.ufmg.dees.insane.util.IVector, br.ufmg.dees.insane.util.IMatrix)
     */
    public IMatrix getInternalVariableOperator(IMatrix d, IMatrix d2, IVector n, IMatrix c) {
    	IMatrix dG = new IMatrix(2, d.getNumCol());
        IMatrix auxB = new IMatrix(5, 27);
        
        dG.setZero();
        auxB.setZero();
        IMatrix J1 = this.invertJacobian(this.getJacobian(d, c));
        dG.mul(J1,d);
        
        int j = 0;
        int k = 0;
        for(int i = 0; i < 9; i++){
        	j++;
            auxB.setElement(0, j, dG.getElement(0, i));
            auxB.setElement(1, (j+1), dG.getElement(1, i));
            auxB.setElement(2, j, dG.getElement(1, i));
            auxB.setElement(2, (j+1), dG.getElement(0, i));
            auxB.setElement(3, k, dG.getElement(0, i));
            auxB.setElement(3, j, -n.getElement(i));
            auxB.setElement(4, k, dG.getElement(1, i));
            auxB.setElement(4, (j+1), -n.getElement(i));
            j = j + 2;
            k = k + 3;
        }
        
        IMatrix h = new IMatrix(27, 26);
        h.setZero();
        for(int lin = 0; lin < 24; lin++){
        	for(int col = 0; col < 24; col++){
        		if (lin == col)
        			h.setElement(lin, col, 1);
        	}
        }
        h.setElement(25, 24, 1);
        h.setElement(26, 25, 1);
        
        j = 0;
        for(int i = 0; i < 4; i++){
	        h.setElement(24, j, -0.25);
	        h.setElement(24, (j+3), 0.5);
	        j = j + 6;
        }
        
        IMatrix b = new IMatrix(5,26);
        b.mul(auxB,h);
        
        return(b);
    }

    /* (non-Javadoc)
     * @see lr.ufmg.dees.insane.analysisModel.AnalysisModel#getInternalVarialleOperator(lr.ufmg.dees.insane.util.IMatrix, lr.ufmg.dees.insane.util.IVector, lr.ufmg.dees.insane.util.IMatrix, lr.ufmg.dees.insane.util.IMatrix)
     */
    public IMatrix getInternalVariableOperator(IMatrix d, IMatrix d2, IVector n, IMatrix c, IMatrix u) {
    	IMatrix dG = new IMatrix(2, d.getNumCol());
        IMatrix auxB = new IMatrix(5, 27);
        
        dG.setZero();
        auxB.setZero();
        IMatrix J1 = this.invertJacobian(this.getJacobian(d, c));
        dG.mul(J1,d);
        
        int j = 0;
        int k = 0;
        for(int i = 0; i < 9; i++) 
        {
        	j++;
            auxB.setElement(0, j, dG.getElement(0, i));
            auxB.setElement(1, (j+1), dG.getElement(1, i));
            auxB.setElement(2, j, dG.getElement(1, i));
            auxB.setElement(2, (j+1), dG.getElement(0, i));
            auxB.setElement(3, k, dG.getElement(0, i));
            auxB.setElement(3, j, -n.getElement(i));
            auxB.setElement(4, k, dG.getElement(1, i));
            auxB.setElement(4, (j+1), -n.getElement(i));
            j = j + 2;
            k = k + 3;
        }
        
        IMatrix h = new IMatrix(27, 26);
        h.setZero();
        for(int lin = 0; lin < 24; lin++){
        	for(int col = 0; col < 24; col++){
        		if (lin == col)
        			h.setElement(lin, col, 1);
        	}
        }
        h.setElement(25, 24, 1);
        h.setElement(26, 25, 1);
        
        j = 0;
        for(int i = 0; i < 4; i++){
	        h.setElement(24, j, -0.25);
	        h.setElement(24, (j+3), 0.5);
	        j = j + 6;
        }
        
        IMatrix b = new IMatrix(5,27);
        b.mul(auxB,h);
        
        return(b);
    }

    /* (non-Javadoc)
     * @see br.ufmg.dees.insane.analysisModel.AnalysisModel#getShapeMatrix(br.ufmg.dees.insane.util.IVector)
     */
    public IMatrix getStateVariableOperator(IMatrix d, IVector n, IMatrix c){
        IMatrix matrixN = new IMatrix(3,26);
        matrixN.setZero();
        for(int i = 0; i < 8; i++){
    		matrixN.setElement(0, (3*i), n.getElement(i+9));
            matrixN.setElement(1, ((3*i)+1), n.getElement(i));
            matrixN.setElement(2, ((3*i)+2), n.getElement(i));
        }
        matrixN.setElement(1, 24, n.getElement(8));
        matrixN.setElement(2, 25, n.getElement(8));
        return matrixN;
    }

    /* (non-Javadoc)
	 * @see br.ufmg.dees.insane.analysisModel.AnalysisModel#getGeometricOperator(br.ufmg.dees.insane.util.IVector)
	 */
    public IMatrix getGeometricOperator(IVector n1) {
    	IMatrix n = new IMatrix(3, 18);
    	n.setZero();
    	for(int i = 0; i < 8; i++){
    		n.setElement(0, (i*2), n1.getElement(i+9));
    		n.setElement(1, ((i*2)+1), n1.getElement(i+9));
    	}
		return n;
    }
    
    /* (non-Javadoc)
     * @see br.ufmg.dees.insane.analysisModel.AnalysisModel#getJacobianTransformation(br.ufmg.dees.insane.util.IMatrix)
     */
    public double getJacobianTransformation(IMatrix dl, IMatrix cN){
 		IMatrix jacobian = new IMatrix(2,2);
        jacobian.setZero();
        jacobian.mul(this.getDL(dl), this.getCN(cN));
        double detJ = jacobian.determinantLU();
        return(detJ);
    }
    
    /* (non-Javadoc)
     * @see br.ufmg.dees.insane.analysisModel.AnalysisModel#getTransformationMatrix(br.ufmg.dees.insane.util.IMatrix, br.ufmg.dees.insane.util.IMatrix)
     */
    public IMatrix getTransformationMatrix(IMatrix dl, IMatrix cN) {
    	IMatrix transf = new IMatrix(26,26);
    	transf.setIdentity();
        return transf;
    }
    
    /** Return the jacobian matrix.
	*@param dl The matrix of local derivates.
	*@param cN The matrix of nodal coordinates.
	*@return dl * cN The jacobian matrix.
	*/
	public IMatrix getJacobian(IMatrix dl, IMatrix cN){
 		IMatrix jacobian = new IMatrix(this.getDominion(),this.getDominion());
		jacobian.setZero();
		jacobian.mul(this.getDL(dl), this.getCN(cN));
		return(jacobian);
	}
	
    /** Return the matrix of local derivates.
	*@param dl The matrix of local derivates.
	*@return auxDl The matrix of local derivates.
	*/
	private IMatrix getDL(IMatrix dl){
    	IMatrix auxDl = new IMatrix(2,8);
    	for(int i = 0; i < 2; i++){
    		for(int j = 0; j < 8; j++){
    			auxDl.setElement(i, j, dl.getElement(i, j+9));
    		}
    	}
    	return auxDl;
	}

    /** Return the matrix of nodal coordinates.
	*@param cN The matrix of nodal coordinates.
	*@return auxCN The matrix of nodal coordinates.
	*/
	private IMatrix getCN(IMatrix cN){
    	IMatrix auxCN = new IMatrix(8,2);
    	for(int i = 0; i < 8; i++){
    		for(int j = 0; j < 2; j++){
    			auxCN.setElement(i, j, cN.getElement(i, j));
    		}
    	}
    	return auxCN;
	}

    /* (non-Javadoc)
     * @see br.ufmg.dees.insane.analysisModel.AnalysisModel#ggetDOFLabels(int)
     */
	public ArrayList getDOFLabels(int n){
		ArrayList <PointValues> al = new ArrayList<PointValues>();
		PointValues spv1 = new StringPointValues();
	    spv1.addPointValue("Dz");
	    spv1.addPointValue("Rx");
	    spv1.addPointValue("Ry");

		PointValues spv2 = new StringPointValues();
	    spv2.addPointValue("Rx");
	    spv2.addPointValue("Ry");

	    for(int i=0; i<n; i++) {
			if(i<8){
				al.add(i,spv1);
			}else if(i==8){
				al.add(i,spv2);
			}
		}
		return al;
	}
}
